/**
 * 
 */
package algoritmos;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Vector;

import problema.Utilidades;

import matrices.centro.Clase;

import View.InterfaceVista;
import Control.InterfaceControl;
import Jama.Matrix;

/**
 * @author Jose Antonio Gonzalez, Ambrin Chaudhary
 * 
 */
public class CV {

    public Vector<Matrix> vectMatrices;
    public Vector<Clase> vectClases;
    public boolean cargado = false;
    public boolean cuantizado = false;
    public double T = 20.0;

    public CV(Vector<Matrix> vectMatrices, Vector<Clase> vectClases,
            boolean cargado, double t) {
        super();
        this.vectMatrices = vectMatrices;
        this.vectClases = vectClases;
        this.cargado = cargado;
        T = t;
    }

    public CV() {
        this.vectMatrices = new Vector<Matrix>();
        this.vectClases = new Vector<Clase>();
    }

    public void cargarFichACuantizar(BufferedReader entrada) throws IOException {
        this.vectClases = new Vector<Clase>();
        this.vectMatrices = new Vector<Matrix>();

        try {

            // BufferedReader entrada = new BufferedReader(new
            // FileReader(fichero));

            String s = "";
            do {
                s = entrada.readLine();
                if (s == null) {
                    break;
                } else {
                    StringTokenizer st = new StringTokenizer(s, ",");

                    int i = 0;
                    int cant = st.countTokens();
                    double d[][] = new double[1][cant];
                    while (st.hasMoreTokens()) {

                        String s1 = st.nextToken();
                        double aux = Double.parseDouble(s1);
                        d[0][i] = aux;
                        i++;
                    }

                    vectMatrices.add(new Matrix(d));

                }
            } while (true);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("Error al cargar archivo");
            throw e;
        }

        this.cargado = true;

    //this.cuantizar();

    }

    public void cuantizar(double t) {
        this.T = t;
        this.cuantizar();
    }

    public void cuantizar() {
        for (int i = 0; i < vectMatrices.size(); i++) {
            Matrix m = vectMatrices.get(i);

            if (vectClases.size() == 0) {
                Clase c = new Clase();
                c.CreateCentro(m);

                vectClases.add(c);

            } else // no es el primer vector
            {
                int centro = -1;
                double min = Double.MAX_VALUE;

                for (int j = 0; j < vectClases.size(); j++) {
                    this.vectClases.get(j);
                    Clase c = vectClases.get(j);
                    Matrix mAux = c.getCentro();
                    double aux = Utilidades.dist(mAux, m);
                    min = Math.min(min, aux);
                    if (min == aux) {
                        centro = j;
                    }
                }

                // vamos a ver si hay que actualizar

                if (min < this.T) // Actualizamos un centro marcado por la var
                // centro
                {
                    Clase c = vectClases.get(centro);
                    //
                    double d[][] = new double[1][c.getCentro().getColumnDimension()];
                    c.addElement(m);

                    ArrayList<Matrix> v = c.getElements();
                    for (int h = 0; h < v.size(); h++) {
                        Matrix mAux = v.get(h);
                        for (int k = 0; k < mAux.getColumnDimension(); k++) {
                            d[0][k] += mAux.get(0, k);
                        }

                    }
                    int dimMat = v.get(0).getColumnDimension();
                    int dimClase = v.size();
                    for (int k = 0; k < dimMat; k++) {
                        d[0][k] /= dimClase;
                    }
                    c.setCentro(new Matrix(d));

                } else// no hay qeu actualizar --> creamos un nuevo centro
                {
                    Clase c = new Clase();
                    c.CreateCentro(m);
                    vectClases.add(c);
                }
            }
        }
        this.cuantizado = true;
    }

    public String evaluar(Vector<Double> v) {

        Matrix m = Utilidades.toMatrix(v);
        Clase clase = null;

        int centro = -1;
        double min = Double.MAX_VALUE;

        for (int j = 0; j < vectClases.size(); j++) {
            this.vectClases.get(j);
            Clase c = vectClases.get(j);
            Matrix mAux = c.getCentro();
            double aux = Utilidades.dist(mAux, m);
            min = Math.min(min, aux);
            if (min == aux) {
                centro = j;
            }
        }

        String s = "";
        clase = this.vectClases.get(centro);
        s += "Centro :" + centro;
        s += "Distancia :" + min;

        /*
         * // vamos a ver si hay que actualizar
         * 
         * if(min < this.T) // Actualizamos un centro marcado por la var centro {
         * Clase c = vectClases.get(centro); // double d[][] = new double [1][
         * c.getCentro().getColumnDimension()]; c.addElement(m);
         * 
         * ArrayList<Matrix> v = c.getElements(); for(int h = 0; h<v.size();
         * h++ ) { Matrix mAux = v.get(h); for(int k= 0; k<mAux.getColumnDimension();
         * k++ ) { d[0][k] += mAux.get(0,k); }
         *  } int dimMat = v.get(0).getColumnDimension(); int dimClase =
         * v.size(); for(int k= 0; k<dimMat; k++ ) { d[0][k] /= dimClase; }
         * c.setCentro(new Matrix(d));
         * 
         * vectClases.add(c);
         *  } else// no hay qeu actualizar --> creamos un nuevo centro { Clase c =
         * new Clase(); c.CreateCentro(m); vectClases.add(c); }
         */

        return s;

    }

    public Vector<Clase> getClases() {
        return this.vectClases;
    }

    public Vector<Matrix> getMuestras() {
        return this.vectMatrices;
    }

    public String toStringMatrices() {
        String s = "";
        Matrix m = null;
        for (int i = 0; i < this.vectMatrices.size(); i++) {
            m = this.vectMatrices.get(i);
            s += Utilidades.matrixToString(m) + "\n";
        }

        return s;
    }

    public String toStringCentros() {
        String s = "";
        Clase c = null;
        for (int i = 0; i < this.vectClases.size(); i++) {
            c = this.vectClases.get(i);
            s += Utilidades.matrixToString(c.getCentro()) + "\n";
        }

        return s;
    }
}
